home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- #ifndef lint
- char copyright[] =
- "@(#) Copyright (c) 1987 Regents of the University of California.\n\
- All rights reserved.\n";
- #endif /* not lint */
-
- #ifndef lint
- static char sccsid[] = "@(#)ping.c 4.10 (Berkeley) 10/10/88";
- #endif /* not lint */
-
- #include "defs.h"
-
- /*
- * P I N G . C
- *
- * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
- * measure round-trip-delays and packet loss across network paths.
- *
- * Author -
- * Mike Muuss
- * U. S. Army Ballistic Research Laboratory
- * December, 1983
- * Modified at Uc Berkeley
- *
- * Status -
- * Public Domain. Distribution Unlimited.
- *
- * Bugs -
- * More statistics could always be gathered.
- * This program has to run SUID to ROOT to access the ICMP socket.
- */
-
- char usage[] = "Usage: ping [ -drv ] host [ datasize ] [ npackets ]\n";
- char hnamebuf[MAXHOSTNAMELEN];
- char *pname;
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int sockoptions, on;
- char *destdotaddr;
- char *host_err_str();
- struct hostent *host;
- struct protoent *proto;
-
- on = 1;
- pname = argv[0];
- argc--;
- argv++;
-
- sockoptions = 0;
- while (argc > 0 && *argv[0] == '-') {
- while (*++argv[0]) switch (*argv[0]) {
- case 'd':
- sockoptions |= SO_DEBUG;
- break;
- case 'r':
- sockoptions |= SO_DONTROUTE;
- break;
- case 'v':
- verbose++;
- break;
- }
- argc--, argv++;
- }
- if (argc < 1)
- err_quit(usage);
-
- /*
- * Assume the host is specified by numbers (Internet dotted-decimal)
- * and call inet_addr() to convert it. If that doesn't work, then
- * assume its a name and call gethostbyname() to look it up.
- */
-
- bzero((char *) &dest, sizeof(dest));
- dest.sin_family = AF_INET;
-
- if ( (dest.sin_addr.s_addr = inet_addr(argv[0])) != INADDR_NONE) {
- strcpy(hnamebuf, argv[0]);
- hostname = hnamebuf;
- destdotaddr = NULL;
- } else {
- if ( (host = gethostbyname(argv[0])) == NULL) {
- err_quit("host name error: %s %s",
- argv[0], host_err_str());
- }
- dest.sin_family = host->h_addrtype;
- bcopy(host->h_addr, (caddr_t) &dest.sin_addr, host->h_length);
- hostname = host->h_name;
- destdotaddr = inet_ntoa(dest.sin_addr.s_addr);
- /* convert to dotted-decimal notation */
- }
-
- /*
- * If the user specifies a size, that is the size of the data area
- * following the ICMP header that is transmitted. If the data area
- * is large enough for a "struct timeval", then enable timing.
- */
-
- if (argc >= 2)
- datalen = atoi(argv[1]);
- else
- datalen = DEF_DATALEN;
-
- packsize = datalen + SIZE_ICMP_HDR;
- if (packsize > MAXPACKET)
- err_quit("packet size too large");
- if (datalen >= SIZE_TIME_DATA)
- timing = 1;
-
- /*
- * The user can specify the maximum number of packets to receive.
- */
-
- if (argc > 2)
- npackets = atoi(argv[2]);
-
- /*
- * Fetch our Unix process ID. We use that as the "ident" field
- * in the ICMP header, to identify this process' packets.
- * This allows multiple copies of ping to be running on a host
- * at the same time. This identifier is needed to separate
- * the received ICMP packets (since all readers of an ICMP
- * socket get all the received packets).
- */
-
- ident = getpid() & 0xffff;
-
- /*
- * Create the socket.
- */
-
- if ( (proto = getprotobyname("icmp")) == NULL)
- err_quit("unknown protocol: icmp");
- if ( (sockfd = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0)
- err_sys("can't create raw socket");
- if (sockoptions & SO_DEBUG)
- if (setsockopt(sockfd, SOL_SOCKET, SO_DEBUG, &on,
- sizeof(on)) < 0)
- err_sys("setsockopt SO_DEBUG error");
- if (sockoptions & SO_DONTROUTE)
- if (setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &on,
- sizeof(on)) < 0)
- err_sys("setsockopt SO_DONTROUTE error");
-
- printf("PING %s", hostname);
- if (destdotaddr)
- printf(" (%s)", destdotaddr);
- printf(": %d data bytes\n", datalen);
- tmin = 99999999;
-
- setlinebuf(stdout); /* one line at a time */
-
- signal(SIGINT, sig_finish); /* to let user stop program */
- signal(SIGALRM, sig_alarm); /* invoked every second */
-
- sig_alarm(); /* start the output going */
-
- recv_ping(); /* and start the receive */
-
- /* NOTREACHED */
- }
-